package com.ap.core.util;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * The interface for a type of map that supports TypedKeys as opposed to arbitrary objects.
 */
public interface TypedMap {

    /**
     * The size of the map.
     * @see java.util.Map#size()
     * @return the size of the map.
     */
    int size();

    /**
     * Whether the map is empty
     * @see java.util.Map#isEmpty()
     * @return whether the map is empty.
     */
    boolean isEmpty();

    /**
     * Whether the map contains the typed key.
     * @see java.util.Map#containsKey(Object)
     * @param key the typed key to check for.
     * @return true if an entry using the typed key exists, false otherwise.
     */
    boolean containsKey(TypedKey key);

    /**
     * Whether the map contains the value.
     * @see java.util.Map#containsValue(Object)
     * @param value the value to check for.
     * @return true if one or more entries for this value exist in the map.
     */
    boolean containsValue(Object value);

    /**
     * Get the value associated with the typed key.
     * @see java.util.Map#get(Object)
     * @param key the typed key to use for retrieval.
     * @param <T> The type of the object to be retrieved.
     * @return the value associated with the key or null - encapsulated in a Nullable.
     */
    <T> Nullable<T> get(TypedKey<T> key);

    /**
     * Put the value into the map, associated with the typed key.
     * @see java.util.Map#put(Object, Object)
     * @param key the typed key to use for storage and retrieval.
     * @param value the value to store.
     * @param <T> The type of the value to store.
     * @return any previous value stored against the key encapsulated in an Nullable.
     */
    <T> Nullable<T> put(TypedKey<T> key, T value);

    /**
     * Remove any value associated with the key from the map.
     * @see java.util.Map#remove(Object)
     * @param key the typed key for which to remove the value.
     * @param <T> the type of the key to be remoced.
     * @return a Nullable containing the value if it existed or null if it didn't that has been removed.
     */
    <T> Nullable<T> remove(TypedKey<T> key);

    /**
     * Add all the values from the passed in map to this map.
     * @see java.util.Map#putAll(java.util.Map)
     * @param m the TypedMap whose entries should be added.
     */
    void putAll(TypedMap m);

    /**
     * Remove all entries from this typed map.
     * @see java.util.Map#remove(Object)
     */
    void clear();

    /**
     * Get the set of all the typed keys that have values stored in the map.
     * @see java.util.Map#keySet()
     * @return the set of all the typed keys that have values stored in the map.
     */
    Set<TypedKey> keySet();

    /**
     * Get a collection of all the values stored in the typed map.
     * @see java.util.Map#values()
     * @return a collection of all the values stored in the typed map.
     */
    Collection values();

    /**
     * Get a set of all the entries that are stored in the typed map.
     * @see java.util.Map#entrySet()
     * @return a set of all the entries that are stored in the typed map.
     */
    Set<Map.Entry<TypedKey, Object>> entrySet();

    /**
     * Get a standard {@link java.util.Map} containing the same data as the TypedMap.
     * @return a map containing the same data as the TypedMap.
     */
    Map<TypedKey, Object> asStandardMap();

}
